﻿using AE_BEPUPhysics_Addition;
using BEPUphysics.BroadPhaseEntries;
using BEPUphysics.BroadPhaseEntries.MobileCollidables;
using BEPUphysics.CollisionTests;
using BEPUphysics.NarrowPhaseSystems.Pairs;
using BEPUutilities;
using FixMath.NET;
using GameConfig;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TEngine;
using UnityEngine;
using UnityEngine.Events;

namespace GameLogic
{
    public class BulletControl:MonoBehaviour
    {
        WeaponData m_WeaponData;
        BulletDataContainer m_DataContainer;
        AEBoxVolumnBaseCollider m_Collider;
        BulletView m_View;
        BEPUutilities.Vector3 m_EmitPos;
        Influence m_Influence;

        UnityAction<BulletControl> m_OnExplotionCallback;

        public UnityAction<BulletControl> OnExplotionCallback { get => m_OnExplotionCallback; set => m_OnExplotionCallback = value; }
        public Influence Influence { get => m_Influence;}
        public AEBoxVolumnBaseCollider Collider { get => m_Collider; set => m_Collider = value; }

        public static BulletControl Create(WeaponData weaponData, BEPUutilities.Vector3 emitPos, Influence influence)
        {
            var gameObj = PoolManager.Instance.GetGameObjectCustomFlagName("Bullet" + weaponData.Cfg.Id, "Assets/AssetRaw/Bullet/Prefabs/Bullet.prefab");
            var control = gameObj.GetComponent<BulletControl>();
            control.Init(weaponData, emitPos, influence);
            return control;
        }
        ~BulletControl()
        {

        }

        void Init(WeaponData data, BEPUutilities.Vector3 emitPos, Influence influence)
        {
            m_Exploded = false;
            m_Influence = influence;
            m_WeaponData = data;
            m_DataContainer = new BulletDataContainer(m_WeaponData);
            m_View = gameObject.GetComponent<BulletView>();
            m_View.Init(data);
            m_Collider = gameObject.GetComponentInChildren<AEBoxVolumnBaseCollider>();
            m_EmitPos = emitPos;
            m_Collider.gameObject.transform.position = emitPos.ToFloat();
            m_Collider.gameObject.transform.rotation = m_WeaponData.Rotation.ToFloat();
            UpdateView();

            FightLogicManager.Instance.RegisterCollider(m_Collider);
            m_Collider.SetCollisionRole(BEPUphysics.CollisionRuleManagement.CollisionRule.NoSolver);
            m_Collider.Events.ContactCreated += OnContactCreated;
            m_Collider.SetLinearDamping(0);
            Emit();
        }

        //private void OnContactCreated(EntityCollidable sender, Collidable other, CollidablePairHandler pair)
        //{
        //    throw new NotImplementedException();
        //}

        public void SetSpecificRule(BaseVolumnBaseCollider collider, BEPUphysics.CollisionRuleManagement.CollisionRule role)
        {
            BaseVolumnBaseCollider j;
            m_Collider.SetSpecificRole(collider, role);
        }
        bool m_Exploded = false;
        private void OnContactCreated(EntityCollidable sender, Collidable other, CollidablePairHandler pair, ContactData contact)
        {
            var senderCollider = FightLogicManager.Instance.GetCollider(sender.UnityColliderID);
            var otherCollider = FightLogicManager.Instance.GetCollider(other.UnityColliderID);

            var shipControl = ShipControl.TryGetShipControl(otherCollider);
            if(shipControl)
            {
                shipControl.BeDamaged(m_WeaponData.Cfg.Damage);
                Explotion();
            }
            //Debug.Log("Colliction Sender = " + senderCollider.transform.parent.parent.gameObject.name);
        }
        void Explotion()
        {
            if (m_Exploded)
                return;
            m_Exploded = true;
            m_Collider.Clear();
            FightLogicManager.Instance.UnregisterCollider(m_Collider);
            m_OnExplotionCallback(this);
            PoolManager.Instance.PushGameObject(gameObject);
        }
        void Emit()
        {
            m_Collider.SetPosition(new BEPUutilities.Vector2(m_EmitPos.X, m_EmitPos.Y));

            var dir = m_WeaponData.Direction;
            dir.Normalize();
            m_Collider.SetVeolicty(dir * m_WeaponData.Cfg.BulletBaseVelocity / 1000m);
            m_Collider.SetOrientation(m_WeaponData.Rotation);
        }

        public void DoLogic()
        {
            var velocity = m_Collider.GetVelocity();
            var moveDir = velocity;
            var changeVelocity = moveDir * (m_WeaponData.Cfg.BulletAccelerationVelocity / 1000m);
            velocity += changeVelocity;
            m_Collider.SetVeolicty(velocity);
            //m_DataContainer.Data.FlyRange -= ;
            if((int)((m_EmitPos - m_Collider.GetPosition()).Length() * 1000) > m_WeaponData.Cfg.ShotRange)
            {
                Explotion();
            }
        }
        private void Update()
        {
            UpdateView();
        }

        void UpdateView()
        {
            if (m_View && m_Collider)
            {
                m_View.SpriteRenderer.gameObject.transform.position = m_Collider.transform.position;
                m_View.SpriteRenderer.gameObject.transform.rotation = m_Collider.transform.rotation;
            }
        }
    }
}
